#include "menu.h"

// 外部函数声明
extern void drawBatteryStatus();

// ====================================================================================
// BaseMenu 类实现 - 提供通用菜单功能
// ====================================================================================
BaseMenu::BaseMenu(Screen& screen, Keys& keys)
  : _screen(screen), _keys(keys) {}

void BaseMenu::drawMenuTitle(const String& title) {
  _screen.textWhite();
  _screen.spr.fillRect(0, 145, 240, 40, TFT_BLACK);
  _screen.spr.drawString(title, 120, 150, 4);
}

void BaseMenu::clearMenuArea() {
  _screen.spr.fillRect(0, 440, 240, 25, TFT_BLACK);
}

void BaseMenu::pushToScreen() {
  lcd_PushColors(0, 0, _screen.spr.width(), _screen.spr.height(), (uint16_t*)_screen.spr.getPointer());
}

void BaseMenu::drawRoundRectIndicators(int activeIndex, int totalCount, int startY, const int positions[]) {
  for (int i = 0; i < totalCount; i++) {
    uint16_t color = (i == activeIndex) ? TFT_CYAN : TFT_VIOLET;
    _screen.spr.fillSmoothRoundRect(positions[i], startY, 20, 12, 3, color, TFT_BLACK);
  }
}

void BaseMenu::drawCircleIndicators(int activeIndex, int totalCount, const int positions[]) {
  for (int i = 0; i < totalCount; i++) {
    uint16_t color = (i == activeIndex) ? TFT_CYAN : TFT_VIOLET;
    _screen.spr.fillSmoothCircle(positions[i], 456, 6, color, TFT_BLACK);
  }
}

void BaseMenu::drawImage(int x, int y, int width, int height, const unsigned short* image) {
  _screen.spr.pushImage(x, y, width, height, image);
}

// ====================================================================================
// Menu 主菜单类实现
// ====================================================================================

/**
 * @brief Menu构造函数
 * @param screen 屏幕对象引用
 * @param keys 按键对象引用
 * @details 初始化主菜单的菜单名称数组和回调函数指针数组
 */
Menu::Menu(Screen& screen, Keys& keys)
  : BaseMenu(screen, keys) {
  // 初始化菜单名称数组（6个主菜单项）
  _menuName[0] = "NRF遥控";
  _menuName[1] = "本机游戏";
  _menuName[2] = "双人对战";
  _menuName[3] = "网络信息";
  _menuName[4] = "蓝牙手柄";
  _menuName[5] = "系统设置";

  // 初始化回调函数指针数组为nullptr，防止野指针
  for (int i = 0; i < MENU_COUNT; i++) {
    _callbacks[i] = nullptr;
  }
}

void Menu::setNRFControlCallback(void (*callback)()) {
  _callbacks[0] = callback;
}
void Menu::setLocalGameCallback(void (*callback)()) {
  _callbacks[1] = callback;
}
void Menu::setVSGameCallback(void (*callback)()) {
  _callbacks[2] = callback;
}
void Menu::setNetInfoCallback(void (*callback)()) {
  _callbacks[3] = callback;
}
void Menu::setBtGamepadCallback(void (*callback)()) {
  _callbacks[4] = callback;
}
void Menu::setSystemSetCallback(void (*callback)()) {
  _callbacks[5] = callback;
}

void Menu::show() {
  bool pushFlag = true;
  int menuIndex = 0;

  _screen.textWhite();

  while (true) {
    // 处理左右按键导航
    if (_keys.left.pressed()) {
      menuIndex = (menuIndex - 1 + MENU_COUNT) % MENU_COUNT;
      pushFlag = true;
    } else if (_keys.right.pressed()) {
      menuIndex = (menuIndex + 1) % MENU_COUNT;
      pushFlag = true;
    }

    // 刷新显示
    if (pushFlag) {
      drawMainMenu(menuIndex);
      pushFlag = false;
    }

    // 处理确认键
    if (_keys.o.pressed()) {
      if (_callbacks[menuIndex] != nullptr) {
        _callbacks[menuIndex]();
        pushFlag = true;
      }
    }

    delay(10);
  }
}

void Menu::drawMainMenu(int menuIndex) {
  drawMenuTitle(_menuName[menuIndex]);
  drawBatteryStatus();

  // 绘制指示器
  const int positions[6] = { 20, 56, 92, 128, 164, 200 };
  drawRoundRectIndicators(menuIndex, MENU_COUNT, 450, positions);

  // 绘制对应图标
  const unsigned short* images[MENU_COUNT] = {
    image_data_1nrf,
    image_data_2game,
    image_data_3vs,
    image_data_4info,
    image_data_5ble,
    image_data_6set
  };
  drawImage(20, 220, 200, 200, images[menuIndex]);

  pushToScreen();
}

// ====================================================================================
// NRFMenu NRF遥控菜单类实现
// ====================================================================================

/**
 * @brief NRFMenu构造函数
 * @param screen 屏幕对象引用
 * @param keys 按键对象引用
 * @details 初始化NRF遥控菜单的菜单名称数组和回调函数指针数组
 */
NRFMenu::NRFMenu(Screen& screen, Keys& keys)
  : BaseMenu(screen, keys) {
  // 初始化NRF遥控菜单名称数组（6个遥控选项）
  _nrfName[0] = "皮卡";
  _nrfName[1] = "货车";
  _nrfName[2] = "坦克";
  _nrfName[3] = "无人机";
  _nrfName[4] = "挖掘机";
  _nrfName[5] = "舰船";

  // 初始化回调函数指针数组为nullptr，防止野指针
  for (int i = 0; i < NRF_COUNT; i++) {
    _callbacks[i] = nullptr;
  }
}

void NRFMenu::setPickupCallback(void (*callback)()) {
  _callbacks[0] = callback;
}
void NRFMenu::setTruckCallback(void (*callback)()) {
  _callbacks[1] = callback;
}
void NRFMenu::setTankCallback(void (*callback)()) {
  _callbacks[2] = callback;
}
void NRFMenu::setDroneCallback(void (*callback)()) {
  _callbacks[3] = callback;
}
void NRFMenu::setExcavatorCallback(void (*callback)()) {
  _callbacks[4] = callback;
}
void NRFMenu::setShipCallback(void (*callback)()) {
  _callbacks[5] = callback;
}

void NRFMenu::show() {
  bool pushFlag = true;
  int nrfIndex = 0;

  _screen.textWhite();

  while (true) {
    if (_keys.left.pressed()) {
      nrfIndex = (nrfIndex - 1 + NRF_COUNT) % NRF_COUNT;
      pushFlag = true;
    } else if (_keys.right.pressed()) {
      nrfIndex = (nrfIndex + 1) % NRF_COUNT;
      pushFlag = true;
    }

    if (pushFlag) {
      drawNRFMenu(nrfIndex);
      pushFlag = false;
    }

    if (_keys.o.pressed()) {
      if (_callbacks[nrfIndex] != nullptr) {
        _callbacks[nrfIndex]();
        pushFlag = true;
      }
    } else if (_keys.x.pressed()) {
      clearMenuArea();
      Serial.println("返回主菜单");
      break;
    }

    delay(10);
  }
}

void NRFMenu::drawNRFMenu(int nrfIndex) {
  drawMenuTitle(_nrfName[nrfIndex]);
  clearMenuArea();
  drawBatteryStatus();

  // 绘制指示器
  const int positions[6] = { 30, 66, 102, 138, 174, 210 };
  drawCircleIndicators(nrfIndex, NRF_COUNT, positions);

  // 绘制图标
  const unsigned short* images[NRF_COUNT] = {
    image_data_1_1pickup,
    image_data_1_2truck,
    image_data_1_3tank,
    image_data_1_4drone,
    image_data_1_5excavator,
    image_data_1_6ship
  };
  drawImage(20, 220, 200, 200, images[nrfIndex]);

  pushToScreen();
}

// ====================================================================================
// GameMenu 游戏菜单类实现
// ====================================================================================

/**
 * @brief GameMenu构造函数
 * @param screen 屏幕对象引用
 * @param keys 按键对象引用
 * @details 初始化游戏菜单的菜单名称数组和回调函数指针数组
 */
GameMenu::GameMenu(Screen& screen, Keys& keys)
  : BaseMenu(screen, keys) {
  // 初始化游戏菜单名称数组（5个游戏）
  _gameName[0] = "贪吃蛇";
  _gameName[1] = "打砖块";
  _gameName[2] = "飞机大战";
  _gameName[3] = "2048";
  _gameName[4] = "俄罗斯方块";

  // 初始化回调函数指针数组为nullptr，防止野指针
  for (int i = 0; i < GAME_COUNT; i++) {
    _callbacks[i] = nullptr;
  }
}

void GameMenu::setSnakeCallback(void (*callback)()) {
  _callbacks[0] = callback;
}
void GameMenu::setBrickCallback(void (*callback)()) {
  _callbacks[1] = callback;
}
void GameMenu::setPlaneCallback(void (*callback)()) {
  _callbacks[2] = callback;
}
void GameMenu::setNum2048Callback(void (*callback)()) {
  _callbacks[3] = callback;
}
void GameMenu::setTetrisCallback(void (*callback)()) {
  _callbacks[4] = callback;
}

void GameMenu::show() {
  bool gameFlag = true;
  int gameIndex = 0;

  _screen.textWhite();

  while (true) {
    if (_keys.left.pressed()) {
      gameIndex = (gameIndex - 1 + GAME_COUNT) % GAME_COUNT;
      gameFlag = true;
    } else if (_keys.right.pressed()) {
      gameIndex = (gameIndex + 1) % GAME_COUNT;
      gameFlag = true;
    }

    if (gameFlag) {
      drawGameMenu(gameIndex);
      gameFlag = false;
    }

    if (_keys.o.pressed()) {
      if (_callbacks[gameIndex] != nullptr) {
        _callbacks[gameIndex]();
        gameFlag = true;
      }
    } else if (_keys.x.pressed()) {
      _screen.clearAndCenter();
      Serial.println("返回主菜单");
      break;
    }

    delay(10);
  }
}

void GameMenu::drawGameMenu(int gameIndex) {
  drawMenuTitle(_gameName[gameIndex]);
  clearMenuArea();
  drawBatteryStatus();

  // 绘制指示器
  const int positions[5] = { 48, 84, 120, 156, 192 };
  drawCircleIndicators(gameIndex, GAME_COUNT, positions);

  // 绘制图标
  const unsigned short* images[GAME_COUNT] = {
    image_data_2_1snake,
    image_data_2_2brick,
    image_data_2_3plane,
    image_data_2_4num2048,
    image_data_2_5tetris
  };
  drawImage(20, 220, 200, 200, images[gameIndex]);

  pushToScreen();
}

// ====================================================================================
// VSMenu 对战菜单类实现
// ====================================================================================

/**
 * @brief VSMenu构造函数
 * @param screen 屏幕对象引用
 * @param keys 按键对象引用
 * @details 初始化双人对战菜单的菜单名称数组和回调函数指针数组
 */
VSMenu::VSMenu(Screen& screen, Keys& keys)
  : BaseMenu(screen, keys) {
  // 初始化对战菜单名称数组（1个对战游戏）
  _vsName[0] = "弹球";

  // 初始化回调函数指针数组为nullptr，防止野指针
  for (int i = 0; i < VS_COUNT; i++) {
    _callbacks[i] = nullptr;
  }
}

void VSMenu::setBallCallback(void (*callback)()) {
  _callbacks[0] = callback;
}

void VSMenu::show() {
  bool vsFlag = true;
  int vsIndex = 0;

  _screen.textWhite();

  while (true) {
    if (_keys.left.pressed() || _keys.right.pressed()) {
      vsFlag = true;
    }

    if (vsFlag) {
      drawVSMenu(vsIndex);
      vsFlag = false;
    }

    if (_keys.o.pressed()) {
      if (_callbacks[vsIndex] != nullptr) {
        _callbacks[vsIndex]();
        vsFlag = true;
      }
    } else if (_keys.x.pressed()) {
      _screen.clearAndCenter();
      Serial.println("返回主菜单");
      break;
    }

    delay(10);
  }
}

void VSMenu::drawVSMenu(int vsIndex) {
  drawMenuTitle(_vsName[vsIndex]);
  clearMenuArea();
  drawBatteryStatus();

  // 绘制单个指示器
  _screen.spr.fillSmoothCircle(120, 456, 6, TFT_CYAN, TFT_BLACK);

  // 绘制图标
  drawImage(20, 220, 200, 200, image_data_3_1_ball);

  pushToScreen();
}

// ====================================================================================
// InfoMenu 信息菜单类实现
// ====================================================================================

/**
 * @brief InfoMenu构造函数
 * @param screen 屏幕对象引用
 * @param keys 按键对象引用
 * @details 初始化网络信息菜单的菜单名称数组和回调函数指针数组
 */
InfoMenu::InfoMenu(Screen& screen, Keys& keys)
  : BaseMenu(screen, keys) {
  // 初始化信息菜单名称数组（3个信息项）
  _infoName[0] = "哔哩哔哩";
  _infoName[1] = "天气预报";
  _infoName[2] = "股票基金";

  // 初始化回调函数指针数组为nullptr，防止野指针
  for (int i = 0; i < INFO_COUNT; i++) {
    _callbacks[i] = nullptr;
  }
}

void InfoMenu::setBilibiliCallback(void (*callback)()) {
  _callbacks[0] = callback;
}
void InfoMenu::setWeatherCallback(void (*callback)()) {
  _callbacks[1] = callback;
}
void InfoMenu::setStockCallback(void (*callback)()) {
  _callbacks[2] = callback;
}

void InfoMenu::show() {
  bool infoFlag = true;
  int infoIndex = 0;

  _screen.textWhite();

  while (true) {
    if (_keys.left.pressed()) {
      infoIndex = (infoIndex - 1 + INFO_COUNT) % INFO_COUNT;
      infoFlag = true;
    } else if (_keys.right.pressed()) {
      infoIndex = (infoIndex + 1) % INFO_COUNT;
      infoFlag = true;
    }

    if (infoFlag) {
      drawInfoMenu(infoIndex);
      infoFlag = false;
    }

    if (_keys.o.pressed()) {
      if (_callbacks[infoIndex] != nullptr) {
        _callbacks[infoIndex]();
        infoFlag = true;
      }
    } else if (_keys.x.pressed()) {
      _screen.clearAndCenter();
      Serial.println("返回主菜单");
      break;
    }

    delay(10);
  }
}

void InfoMenu::drawInfoMenu(int infoIndex) {
  drawMenuTitle(_infoName[infoIndex]);
  clearMenuArea();
  drawBatteryStatus();

  // 绘制指示器
  const int positions[3] = { 84, 120, 156 };
  drawCircleIndicators(infoIndex, INFO_COUNT, positions);

  // 特殊处理bilibili图标高度
  if (infoIndex == 0) {
    _screen.spr.fillRect(0, 400, 240, 20, TFT_BLACK);
    drawImage(20, 220, 200, 181, image_data_4_1_bilibili);
  } else {
    const unsigned short* images[2] = { image_data_4_2_weather, image_data_4_3_stock };
    drawImage(20, 220, 200, 200, images[infoIndex - 1]);
  }

  pushToScreen();
}

// ====================================================================================
// SystemMenu 系统设置菜单类实现
// ====================================================================================

/**
 * @brief SystemMenu构造函数
 * @param screen 屏幕对象引用
 * @param keys 按键对象引用
 * @details 初始化系统设置菜单的菜单名称数组和回调函数指针数组
 */
SystemMenu::SystemMenu(Screen& screen, Keys& keys)
  : BaseMenu(screen, keys) {
  // 初始化系统设置菜单名称数组（2个设置项）
  _setName[0] = "按键测试";
  _setName[1] = "陀螺仪立方体";

  // 初始化回调函数指针数组为nullptr，防止野指针
  for (int i = 0; i < SYSTEM_COUNT; i++) {
    _callbacks[i] = nullptr;
  }
}

void SystemMenu::setKeysTestCallback(void (*callback)()) {
  _callbacks[0] = callback;
}
void SystemMenu::setCubeCallback(void (*callback)()) {
  _callbacks[1] = callback;
}

void SystemMenu::show() {
  bool setFlag = true;
  int setIndex = 0;

  _screen.textWhite();

  while (true) {
    if (_keys.left.pressed()) {
      setIndex = (setIndex - 1 + SYSTEM_COUNT) % SYSTEM_COUNT;
      setFlag = true;
    } else if (_keys.right.pressed()) {
      setIndex = (setIndex + 1) % SYSTEM_COUNT;
      setFlag = true;
    }

    if (setFlag) {
      drawSystemMenu(setIndex);
      setFlag = false;
    }

    if (_keys.o.pressed()) {
      if (_callbacks[setIndex] != nullptr) {
        _callbacks[setIndex]();
        setFlag = true;
      }
    } else if (_keys.x.pressed()) {
      _screen.clearAndCenter();
      Serial.println("返回主菜单");
      break;
    }

    delay(10);
  }
}

void SystemMenu::drawSystemMenu(int setIndex) {
  drawMenuTitle(_setName[setIndex]);
  clearMenuArea();
  drawBatteryStatus();

  // 绘制指示器
  const int positions[2] = { 102, 138 };
  drawCircleIndicators(setIndex, SYSTEM_COUNT, positions);

  // 绘制图标
  const unsigned short* images[SYSTEM_COUNT] = {
    image_data_6_1_keysTest,
    image_data_6_2_cube
  };
  drawImage(20, 220, 200, 200, images[setIndex]);

  pushToScreen();
}
